-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Test shared library on Windows #186
Conversation
8dda993
to
fa98b95
Compare
This is POC for solving issue #182. I've created a small shared library (uuid-shared) and test application (uuid-app), uuid-app links with uuid-shared and it compiles successfully on both Linux and Windows. |
Note that from python we are just using the oc_python.c file... so if we have an header file for that code, then one can build C# like the python code. C# has a similar interface as python c_types, e.g. add the call format to the dll in the C# code. |
You mean adding |
correct. then we can also run the python (client) code on windows. not sure if we want to do the same API as JAVA, that is a considerable amount of work. |
Sure, no problem, I can do it, shouldn't take that long to do the Windows part. |
CMakeLists.txt
Outdated
) | ||
|
||
# Python client | ||
if(UNIX OR WIN32) | ||
set(client-python-lib-obj |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I don't think I can reuse the .o files. I need different annotations when I compile for static
or shared
lib.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Oxymoron79 I guess the solution here is to create shared version of the object libraries (common-obj
and common-obj-shared
, etc.), since they have differing compile definitions. Though they differ only in the compile definitions, so the CMake code for both targets will be very similar. I should probably create a CMake function that creates a library (both static and shared) target to avoid most of the duplicity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that really necessary? The point of the object libraries is to generate static and dynamic libraries without the need to recompile the source...
Is your reasoning for this the declspec(dllexport)
annotation for Windows? If so, I doubt that different object files are needed, because the user of the DLL has to change the annotation to declspec(dllimport)
when linking to the binary (which was compiled with declspec(dllexport)
). But my knowledge of Windows development is limited - so take that with a grain of salt 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like avoid the duplicity if possible, but when I compile libiotivity-lite-client-python.so.2.2.5
and examine the public symbols using nm -D
command - I see that all global functions from common-obj
, tinycbor-master
, client-obj
and python-obj
are public. Thus, adding C_VISIBILITY
to the final shared library target had no effect. It seems that I have to compile the .o
files with the macro definitions for a shared library, linking is not enough. However, I haven't tried it the other way around, add definitions for shared library to the object library targets. If static library targets won't break then that could be the way.
(OT: iotivity builds by CYGWIN and MINGW seem to be broken, but I think I've found the issue; fun for Friday afternoon :D )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand https://cmake.org/cmake/help/latest/policy/CMP0063.html correctly, you can set this policy to NEW
and then set the C_VISIBILITY
on the object library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(OT: iotivity builds by CYGWIN and MINGW seem to be broken, but I think I've found the issue; fun for Friday afternoon :D )
I came across this issue as well. One of our Windows developers found that adding this:
#ifdef __MINGW32__
#undef interface
#endif
in port/windows/tcpadapter.c
and port/windows/network_addresses.c
after the include statements fixes the build.
To me, this seems like quite a hack - so I didn't propose the fix upstream. And I also don't know whether CYGWIN and MINGW build are supported by iotivity-lite.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, that looks indeed relevant. Though I still think that this code is problematic:
#ifdef OC_SHARED_LIBRARY #ifdef OC_SHARED_LIBRARY_EXPORT #define OC_API OC_EXPORT #else /* !OC_SHARED_LIBRARY_EXPORT*/ #define OC_API OC_IMPORT #endif /* OC_SHARED_LIBRARY_EXPORT */ #else /* !OC_SHARED_LIBRARY */ #define OC_API #endif /* OC_SHARED_LIBRARY */I'm reading about
dllexport
and if I understand it correctly, whatever the compiler does with the attribute is compiled into the.o
file. I see no way around the fact that the.o
files are different between static and shared libraries. Shared libraries needOC_SHARED_LIBRARY
andOC_SHARED_LIBRARY_EXPORT
definitions during compilation. The only way this works is by compiling the object files with those definitions and hoping that a static library doesn't have a problem with that.
I think that it is correct to apply the visibility also on static libraries (btw the current visibility default
made all symbols globally visible anyways). So, applying the compile definitions to the object library would promote the correct symbol visibility to the static and the shared library, right?
Though I can think of one side effect, if you compile a static lib from such object files and then link that static lib into a dynamic library, I think the symbols from the static lib will be exposed as global symbols in the final shared library files since they will have the export attribute.
Yes, that's true. I found this question (with an answer) also on stackoverflow: https://stackoverflow.com/questions/2222162/how-to-apply-fvisibility-option-to-symbols-in-static-libraries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, seems like we should be able to get both static and shared libraries from object on Unixes. Not sure what will happen on MSVC, but I guess if my testing app links and runs it should be alright ...?
Though if the definitions will be added to both static and shared libraries I should change the names: OC_SHARED_LIBRARY
-> OC_LIBRARY
and OC_SHARED_LIBRARY_EXPORT
-> OC_LIBRARY_EXPORT
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, seems like we should be able to get both static and shared libraries from object on Unixes. Not sure what will happen on MSVC, but I guess if my testing app links and runs it should be alright ...?
Yes, I think so as well.
Though if the definitions will be added to both static and shared libraries I should change the names:
OC_SHARED_LIBRARY
->OC_LIBRARY
andOC_SHARED_LIBRARY_EXPORT
->OC_LIBRARY_EXPORT
.
Sounds good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to work. Compilation of testing apps that use static lib (uuid-app-static
) and shared lib (uuid-app-shared
) generated from object lib succeeds on both Linux and Win (see PR jobs). I've also examined uuid-shared
with nm -D
on Linux and with dumpbin /exports
on Win10 locally and the lib only has the manually exposed symbols visible.
Additional notes:
- CMP0063 is set to NEW by default, so I skipped setting it explicitly
- When compiling a static lib into a shared lib, gcc (at least my 9.3 version) seems to automatically hide all symbols from static library. So one must add compiler flags to make them visible, however this is not an interesting use case currently, so I didn't pursue it further.
OK, so I'll remove the uuid-* testing stuff and we can start annotating public functions and enabling compilation of DLLs on Windows. @WAvdBeek which functions are considered to be public, only those with headers in include/
folder? Any other? (TBH, in my app that links dynamically with libiotivity-client-server.so, I use functions from all over the place, from api
, security
, port
and util
folders at least. But I'll work it out.)
5cb2977
to
6e9560d
Compare
506253e
to
4bea4ae
Compare
Yes, I spent a good half an hour trying to decipher a weird compilation error on a line with a simple definition of a variable named interface. :D Redefining a common word like I think at least MINGW was previously supported or intended to be supported, see the cmake-windows workflow: iotivity-lite/.github/workflows/cmake-windows.yml Lines 25 to 29 in 88c84f5
I had to do some additional updates to the CMakeLists.txt ( |
nope, this yaml file was just copied from somewhere else and I made it work for visual studio only. |
I see, we can get |
4bea4ae
to
2473c45
Compare
what needs to be done before merge? |
Well, I've created testing apps ( |
oc_python.h, so that we can use the python code on windows. For me that would be enough for a merge. |
2473c45
to
e734521
Compare
e734521
to
3cde7a0
Compare
I've removed the testing apps and |
not sure if it is an actual issue that those symbols are exported. those symbols are used internally in the shared object/dll anyway. |
Yes, that's not a problem that the shared library uses those symbols internally, the issue is that the shared library exports those symbols (at least on Unixes). That is they are available to a binary that links with the shared library. Take the
I think we should have same or at least very similar exposed API on all platforms, so additional work is needed. But |
No description provided.